/**
 *
 * Lockbox
 * a Password and Secret Information Manager
 *
 * Created by Nathan Black
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.

 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#import <CoreFoundation/CoreFoundation.h>
#import <Foundation/Foundation.h>
#import <UIKit/CDStructures.h>
#import <UIKit/UIWindow.h>
#import <UIKit/UIView-Hierarchy.h>
#import <UIKit/UIHardware.h>
#import <UIKit/UITable.h>
#import <UIKit/UITableCell.h>
#import <UIKit/UITableColumn.h>
#import <UIKit/UIImageAndTextTableCell.h>
#import <WebCore/WebFontCache.h>
#import "LockboxApp.h"
#import "LockboxOptions.h"

//#define SKIP_PASSWORD 1

@interface LockboxApp (Private)

- (void)setupMainUI;
- (void)addEditOrDeleteItem:(LockboxItem*)item itemDeleted:(BOOL)itemDeleted;
- (void)alertUser:(NSString*)header exception:(NSException*)ex;
- (void)alertUser:(NSString*)header message:(NSString*)msg;
- (void)setupBackground;
- (void)rebuildPwView:(int)state;

@end

@implementation LockboxApp

- (void)dealloc
{
    [_listView release];
    [_itemView release];
    [_optionsView release];
    [_importView release];
    [_pwView release];
    [_window release];

	[super dealloc];
}

////////////// Event Handlers ///////////////
- (void) applicationDidFinishLaunching: (id) unused
{    
    NSString* homedir = [LockboxOptions homedir];
    if (![[NSFileManager defaultManager] fileExistsAtPath:homedir])
    {
        [[NSFileManager defaultManager] createDirectoryAtPath:homedir attributes:nil];
    }

    _storage = [LockboxStorage globalInstance];
    //[self _setSuspendedUnderLock:TRUE];

    // init main window here
    _window = [[UIWindow alloc] initWithContentRect: [UIHardware
        fullScreenApplicationContentRect]];
       
    [_window orderFront: self];
    [_window makeKey: self];
    [_window _setHidden: NO];
    
    struct CGRect rect = [UIHardware fullScreenApplicationContentRect];
    rect.origin.x = rect.origin.y = 0.0f;

    _pwView = [[[LockboxPasswordView alloc] initWithFrame:rect app:self state:([_storage exists] ? LBPP_AUTH : LBPP_NEW)] retain];    
    _transView = [[UITransitionView alloc] initWithFrame:rect];
    [_transView addSubview:_pwView];
    _currView = _pwView;
#ifdef SKIP_PASSWORD
    [_storage loadWithKey:@"aaaaaa"];
    [self setupMainUI];
    [_transView bringSubviewToFront:_listView];
    _currView = _listView;
#endif
    [_window setContentView: _transView]; 
    
}

- (void)alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button
{
    [sheet dismiss];
}

// Use an alert sheet to pop up a message to the user. TODO: use a modal dialog like Installer.app
- (void)alertUser:(NSString*)header exception:(NSException*)ex
{
    [self alertUser:header message:[ex reason]];
}

- (void)alertUser:(NSString*)header message:(NSString*)msg
{
    UIAlertSheet *infoSheet = [[UIAlertSheet alloc] initWithFrame:CGRectMake(0, 0, 0, 0)];
    [infoSheet setTitle:header];
    [infoSheet setBodyText:msg];
    [infoSheet addButtonWithTitle:@"OK"];
    [infoSheet setDelegate:self];
    [infoSheet setAlertSheetStyle:0];
    [infoSheet presentSheetFromAboveView:[[UIWindow keyWindow] contentView]];
}

- (void)applicationWillTerminate
{
    if (_editingItem) {
        [self addEditOrDeleteItem:[_itemView item] itemDeleted:FALSE];
    }
    
    @try {
        if (_currView == _optionsView) {
            [_optionsView saveOptions];
        }
        
        // Save the user data only if they have authenticated.
        if (_listView != nil) {
            NSLog(@"Saving user data...");
            [_storage save];
        }
    }
    @catch (NSException* ex) {
        NSLog(@"***Caught exception during save: %@ reason: %@", [ex name], [ex reason]);
    }
}

- (void)applicationWillSuspend
{
    NSLog(@"applicationWillSuspend");
    //[self alertUser:@"Info" message:@"applicationWillSuspend"];
}

- (void)willSleep
{
    NSLog(@"willSleep");
    if (_currView != _pwView || (_currView == _pwView && [_pwView state] == LBPP_CHANGE)) {
        [self rebuildPwView:LBPP_AUTH];
        if (_currView == _pwView) {
            _currView = _optionsView;
            [_transView bringSubviewToFront:_pwView];
        }
        else {
            [_transView transition:3 fromView:_optionsView toView:_pwView];
        }
    }
}

- (void)applicationWillSuspendUnderLock;
{
    //[self alertUser:@"Info" message:@"applicationWillSuspendUnderLock"];
    NSLog(@"applicationWillSuspendUnderLock");
}

- (void)setupMainUI
{
    struct CGRect rect = [UIHardware fullScreenApplicationContentRect];
    rect.origin.x = rect.origin.y = 0.0f;

    _listView = [[LockboxListView alloc] initWithFrame:rect app:self];
    _itemView = [[LockboxItemView alloc] initWithFrame:rect app:self];
    _itemTypeView = [[LockboxItemTypeView alloc] initWithFrame:rect app:self];
    _tagView = [[LockboxTagView alloc] initWithFrame:rect app:self tagDelegate:_itemView];
    _optionsView = [[LockboxOptionsView alloc] initWithFrame:rect app:self tagDelegate:_listView];
    _importView = [[LockboxImportView alloc] initWithFrame:rect app:self];
    //[_transView setDelegate: self];
    [_transView insertSubview:_listView below:_pwView];
    [_transView insertSubview:_itemView below:_listView];
    [_transView insertSubview:_tagView below:_itemView];
    [_transView insertSubview:_optionsView below:_listView];
    [_transView insertSubview:_importView below:_optionsView];

}

- (void)rebuildPwView:(int)state
{
    struct CGRect rect = [UIHardware fullScreenApplicationContentRect];
    rect.origin.x = rect.origin.y = 0.0f;
    [_pwView removeFromSuperview];
    [_pwView release];
    _pwView = [[[LockboxPasswordView alloc] initWithFrame:rect app:self state:state] retain];
    [_transView insertSubview:_pwView below:_optionsView];
}

////////////// Transitions ////////////////
- (void)transToItemView:(LockboxItem*)item cell:(LockboxTableCell*)cell
{
    NSLog(@"This is transToItemView");
    _lastCell = cell;
    _editingItem = TRUE;
    if (item == NULL) {
        _currView = _itemTypeView;
        [_itemTypeView newItem];
        [_transView transition:1 fromView:_listView toView:_itemTypeView];
    }
    else {
        _currView = _itemView;
        [_itemView setItem:item];
        [_transView transition:1 fromView:_listView toView:_itemView];
    }
}

- (void)transToOptionsView
{
    [_transView transition:2 fromView:_listView toView:_optionsView];
    [_optionsView refresh];
    _currView = _optionsView;
}

- (void)returnFromOptionsView
{
    [_transView transition:1 fromView:_optionsView toView:_listView];
    _currView = _listView;
}

- (void)returnFromTagView
{
    [_transView transition:2 fromView:_tagView toView:_itemView];
    _currView = _itemView;
}

- (void)transToTagView:(NSMutableArray*)tags;
{
    [_transView transition:1 fromView:_itemView toView:_tagView];
    [_tagView setTags:tags];
    _currView = _tagView;
}

/////////// View Accessor Methods ///////////
- (LockboxListView *) getListView {
  return _listView;
}

- (LockboxItemView *) getItemView {
  return _itemView;
}

- (LockboxOptionsView *) getOptionsView {
  return _optionsView;
}

- (LockboxImportView *) getImportView {
  return _importView;
}

- (void)transitionToView:(id)toView withTransition:(int)trans {
    if (toView) {
        [_transView transition:trans toView:toView];
        _currView = toView;
    }
}

- (void)changePassword
{
    // NSLog(@"before - contains _pwView (0x%x): %d", _pwView, (int)[_transView containsView:_pwView]);
    // TODO: I wish I knew why, but pwView isn't displaying upon a transistion at all. The UIKeyboard view might have something to do with it,
    // but it doesn't make sense the above NSLog statement says it's not a subview of _transView - so how did it get removed?
    [self rebuildPwView:LBPP_CHANGE];
    [_transView transition:3 fromView:_optionsView toView:_pwView];
    _currView = _pwView;    
    //[_transView bringSubviewToFront:_pwView];
    //[_pwView forceDisplayIfNeeded];
}

- (void) pwViewFinished
{
    if (_listView == NULL) {
        // user authenticated, as we haven't started up yet.
        [self setupMainUI];
        /* 3: slide up 4: slide down? */
        [_transView transition:4 fromView:_pwView toView:_listView];
        _currView = _listView;
    }
    else if ([_pwView state] == LBPP_CHANGE) {
        // User changed their password; return them to the options
        [_transView transition:5 fromView:_pwView toView:_optionsView];
        _currView = _optionsView;        
    }
    else {
        // User unlocked after a time out; return them to the previous view they were using.
        // TODO there is a flicker whenever this transition is done. It would be nice to remove it.
        [_transView transition:5 fromView:_pwView toView:_currView];    
    }
}

// TODO: Probably should change our transistions to be executed first before any processing, so
// the processing can be done while the UI is animating the transition, offering a more responsive UI.
- (void)returnFromItemView:(LockboxItem*)item itemDeleted:(BOOL)itemDeleted
{
    NSLog(@"This is returnFromItemView: item: %@ itemDeleted: %d", item, (int)itemDeleted);
    [self addEditOrDeleteItem:item itemDeleted:itemDeleted];
    _editingItem = FALSE;
    [_transView transition:2 fromView:_itemView toView:_listView];
    _currView = _listView;        
}

- (void)addEditOrDeleteItem:(LockboxItem*)item itemDeleted:(BOOL)itemDeleted
{
    // Check the lastCell as we're deleting, as the user may have clicked delete while adding
    if (itemDeleted && _lastCell != NULL) {
        NSLog(@"Deleting item: %@", item->key);
        [[_storage items] removeObject:item];
        // TODO: it would be nice to just delete one item instead of rebuilding the table.
        [_listView refresh];
    }
    else if (_lastCell != NULL) {
        NSLog(@"Updating item: %@", item->key);
        [_lastCell refresh];
    }
    else {
        if (item->key != NULL && [item->key length] > 0) {
            NSLog(@"Adding item: %@", item->key);
            [[_storage items] addObject:item];
            [_listView refresh];
        }
        // otherwise don't add a blank item, and the table & storage stay the same
        // Also condition if itemView never loaded (ie user exited from PW Auth screen)
    }
}

/*- (NSMethodSignature*)methodSignatureForSelector:(SEL)selector {
     NSLog(@"LBApp: Requested method for selector: %@", NSStringFromSelector(selector));
     return [super methodSignatureForSelector:selector];
}

- (BOOL)respondsToSelector:(SEL)aSelector {
    NSLog(@"LBApp: Request for selector: %@", NSStringFromSelector(aSelector));
    return [super respondsToSelector:aSelector];
}

- (void)forwardInvocation:(NSInvocation *)anInvocation {
    NSLog(@"LBApp: Called from: %@", NSStringFromSelector([anInvocation selector]));
    [super forwardInvocation:anInvocation];
}*/

@end
